//////////
// 求值应用 eval/apply/quote


#include <memory.h>
#include <stdio.h>
#include "../basic/operator.h"

Cell *op_toplevel(Scheme *sc) {
	log(sc, "syntax/eval", "op_toplevel");
	push_callstack(sc, cell_op_eval_internal, G_NIL, G_NIL);
	sc->op = cell_op_read_internal;
	log(sc, "syntax/eval", "op_toplevel");
	return G_TRUE;
}

Cell* op_eval_internal(Scheme *sc) {
	log(sc, "syntax/eval", "op_eval_internal");
	sc->code = sc->returnValue;
	//String string = cell2str(sc, sc->code);
	sc->op = cell_op_eval;
	log(sc, "syntax/eval", "op_eval_internal");
	return G_TRUE;
}

Cell* op_eval(Scheme *sc) {
	Cell* x;
    Cell* syntax;

	log(sc, "syntax/eval", "op_eval");

    // && !type_of(sc, sc->code, UNKNOWN_TYPE)
	if (is_pointer(sc->code) && !free_pointer(sc->code)) { /* symbol *///符号求值为他绑定的值
        Cell* value = lookup_variable_value(sc, sc->env, sc->code->_name);
        if (!type_of(sc, value, EXCEPTION_TYPE)) {
            sc->returnValue = value;
			log(sc, "syntax/eval", "op_eval");
            return pop_callstack(sc);
        }
	}

    if (type_of(sc, sc->code, PAIR_TYPE)) { //链表求值
		x = car(sc->code);
        syntax = syntax_op(sc, x);
		//if (is_syntax(x)) { /* SYNTAX *///lambda macro if等开头的链表会通过这个分支处理
		if (syntax != G_NIL) { /* SYNTAX *///lambda macro if等开头的链表会通过这个分支处理
			sc->code = cdr(sc->code);
			//sc->op = find_slot_by_symbol(sc, sc->globalObjects, x);  //sc->op = syntax2op(x);
            sc->op = syntax;
			log(sc, "syntax/eval", "op_eval");
			return G_TRUE;
		} else {
			/* first, eval top element and eval arguments */
			push_callstack(sc, cell_op_e0args, G_NIL, sc->code);
			/* If no macros => s_save(sc,OP_E1ARGS, sc->NIL, cdr(sc->code));*/
			sc->code = car(sc->code);
			//计算第一个字段，结果是函数 或者宏
			sc->op = cell_op_eval;
			log(sc, "syntax/eval", "op_eval");
			return G_TRUE;
		}
	} else { //其他类型求值结果就是自身
		sc->returnValue = sc->code;
		log(sc, "syntax/eval", "op_eval");
		return pop_callstack(sc);
	}
}

Cell* op_e0args(Scheme *sc) {
	log(sc, "syntax/eval", "op_e0args");
	sc->code = cdr(sc->code); //(arg ...)
	sc->op = cell_op_e1args;
	log(sc, "syntax/eval", "op_e0args");
	return G_TRUE;

	/*
	//sc->code的形式 (first_expr arg ...) 这里first_expr的求值结果可能是宏也可能是闭包
	if (is_macro(sc->returnValue)) { // macro expansion
		//如果结果是一个宏，那么参数不要进一步的处理，而是交给这个宏去处理
		s_save(sc, op_domacro, G_NIL, G_NIL); //由这个去执行宏生成的代码
		sc->args = cons(sc, sc->code, G_NIL); //sc->args 的形式是 (first_expr arg ...)  注意first_expr也保留了
		sc->code = sc->returnValue;
		//这里把参数交给宏去处理
		sc->op = op_apply;
		return G_TRUE;
	} else {
		sc->code = cdr(sc->code); //(arg ...)
		sc->op = op_e1args;
		return G_TRUE;
	}
	*/
}

Cell* op_e1args(Scheme *sc) {
	log(sc, "syntax/eval", "op_e1args");
	sc->args = cons(sc, sc->returnValue, sc->args);
	//debug(sc);
	if (type_of(sc, sc->code, PAIR_TYPE)) { /* continue *///对每个实参求值
		push_callstack(sc, cell_op_e1args, sc->args, cdr(sc->code));
		sc->code = car(sc->code);
		sc->args = G_NIL;
		sc->op = cell_op_eval;
		log(sc, "syntax/eval", "op_e1args");
		return G_TRUE;
	} else { /* end */// 实参的值求完了 ，用这些实参调用函数
		sc->args = reverse(sc, sc->args);
		sc->code = car(sc->args);
		sc->args = cdr(sc->args);
		sc->op = cell_op_apply;
		log(sc, "syntax/eval", "op_e1args");
		return G_TRUE;
	}
}

Cell* op_apply(Scheme *sc) {
	Cell *x, *y;

	//debug(sc);
	log(sc, "syntax/eval", "op_apply");

	//if (sc->code->_name != NULL) {
	//	Cell* func = lookup_variable_value(sc, sc->env, sc->code->_name);
	//	sc->code = func;
	//}

	//if (type_of(sc, sc->code, PROCEDURE_TYPE)) {/* PROCEDURE */
    if (sc->code != G_NIL && strcmp(sc->code->_type, PROCEDURE_TYPE) == 0) {/* PROCEDURE */
		//sc->op = (sc->code)->_op;
        sc->op = sc->code;
		//sc->op = make_procedure(sc, (sc->code)->_op);  ////????

		log(sc, "syntax/eval", "op_apply");
		return G_TRUE;
	}
	/*
	else if (is_foreign(sc->code)) {
		// Keep nested calls from GC'ing the arglist
		//sc->code的形式foreign_proc
		x = sc->code->_func(sc, sc->args);
		return s_return_helper(sc, x);
	}
	*/
	else if (type_of(sc, sc->code, CLOSURE_TYPE) || type_of(sc, sc->code, PROMISE_TYPE)) { /* CLOSURE */
		/* Should not accept promise */
		//sc->code的形式1 (var_name body ...)
		//sc->code的形式2 ( (var_name ...) body ...)
		//sc->code的形式3 ( (var_name ...   . var_name) body ...)

		Cell* closureCode = car(sc->code);
		Cell* closureEnv = cdr(sc->code);

        Cell* frame = make_vector(sc, DEFAULT_FRAME_SIZE);
        extend_environment(sc, frame, closureEnv);

        //new_frame_in_env(sc, cdr(sc->code)); //局部变量环境

		x = car(closureCode);
		for (y = sc->args; type_of(sc, x, PAIR_TYPE); x = cdr(x), y = cdr(y)) {//sc->code的形式2 3
			if (y == G_NIL) {
				sc->returnValue = make_default_exception(sc, "NOT_ENOUGH_ARGUMENTS", "not enough arguments");
				return pop_callstack(sc);
			}
			else {
				//new_slot_in_env(sc, car(x), car(y)); //绑定函数形参
                add_binding_to_frame(sc, frame, car(x)->_name, car(y), FALSE);
			}
		}

        //debug(sc);

        if (is_variable(x)) {
            add_binding_to_frame(sc, frame, x->_name, y, FALSE); //sc->code的形式1 3
        } else if (x != G_NIL) {
            sc->returnValue = make_default_exception_1(sc, "NOT_A_VARIABLE", "syntax error in closure, not a var: %s", x->_name);
            return pop_callstack(sc);
        }

		sc->code = cdr(closureCode);
		sc->args = G_NIL;
		sc->op = cell_op_begin;
		log(sc, "syntax/eval", "op_apply");
		return G_TRUE;
	} else if (type_of(sc, sc->code, CONTINUATION_TYPE)) { /* CONTINUATION */
		sc->callStack = cdr(sc->code);
		sc->returnValue = (sc->args != G_NIL ? car(sc->args) : G_NIL);
		log(sc, "syntax/eval", "op_apply");
		return pop_callstack(sc);
	} else {
		sc->returnValue = make_default_exception_1(sc, "ILLEGAL_FUNCTION", "illegal function: %s", cell2str(sc, sc->code));
		return pop_callstack(sc);
	}
}


// (apply + '(1 2 3))
Cell* op_papply(Scheme *sc) {
	log(sc, "syntax/eval", "op_papply");
	sc->code = first(sc->args);
	sc->args = list_star(sc, rest(sc->args));
	sc->op = cell_op_apply;
	log(sc, "syntax/eval", "op_papply");
	return G_TRUE;
}

// (eval code env)
Cell* op_peval(Scheme *sc) {
	log(sc, "syntax/eval", "op_peval");
	if (rest(sc->args) != G_NIL)
		sc->env = second(sc->args); //设置环境
	sc->code = first(sc->args); //要执行的代码
	sc->op = cell_op_eval;
	log(sc, "syntax/eval", "op_peval");
	return G_TRUE;
}

/* call-with-current-continuation */
//将当前堆栈作为参数传给 作为过程的call/cc的参数
/*
Cell* op_continuation(Scheme *sc) {
	sc->code = car(sc->args);
	sc->args = cons(sc, make_continuation(sc, sc->callStack), G_NIL);
	sc->op = cell_op_apply;
	return G_TRUE;
}
*/


Cell* op_quote(Scheme *sc) {
	log(sc, "syntax/eval", "op_quote");
	sc->returnValue = car(sc->code);
	log(sc, "syntax/eval", "op_quote");
	return pop_callstack(sc);
}

void init_eval_operators(Scheme *sc) {
	ADD_OPERATOR(sc, "$toplevel", toplevel);
	ADD_OPERATOR(sc, "$eval-internal", eval_internal);
	ADD_OPERATOR(sc, "$eval", eval);
	ADD_OPERATOR(sc, "$e0args", e0args);
	ADD_OPERATOR(sc, "$e1args", e1args);
	ADD_OPERATOR(sc, "$apply", apply);
	ADD_OPERATOR(sc, "apply", papply);
	ADD_OPERATOR(sc, "eval", peval);
	ADD_OPERATOR(sc, "$quote", quote);

	ADD_SYNTAX(sc, "quote", quote);
}
